//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Logging Application Block
//===============================================================================
//  LogParser - Log File Parser
//  Copyright (C) 2007  Alois Kraus
//  
//  This source code is published under the Microsoft Permissive License (Ms-PL)
//  http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx
//===============================================================================

using System;
using System.Collections.Generic;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace EntLibContrib.Logging.Parser
{
	/// <summary>
	/// This class is responsable for reading filtered LogEntry objects from a normal text file which has previously
	/// been writtern by the Enterprise Library Logging Application Block.
	/// You can use this class to read a text file which was written by the Rolling/File Sink which did use a TextFormatter
	/// which format can be arbitrary.
	/// </summary>
	[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
	public class FilteredLogFileReader : IEnumerable<LogEntry>
	{
		#region Fields
		string myFileName;
		Tokenizer myTokenizer;
		#endregion

		#region Construction
		/// <summary>
		/// Initializes a new instance of the <see cref="FilteredLogFileReader"/> class.
		/// </summary>
		/// <param name="logFileName">Name of the log file.</param>
		/// <param name="entlibLogConfigFile">The entlib log CFG file.</param>
		public FilteredLogFileReader(string logFileName, string entlibLogConfigFile)
			: this(logFileName, new FileConfigurationSource(entlibLogConfigFile), null)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FilteredLogFileReader"/> class.
		/// </summary>
		/// <param name="logFileName">Name of the log file.</param>
		/// <param name="entlibLogConfigFile">The entlib log config file.</param>
		/// <param name="theTimeStampParser">The time stamp parser to use</param>
		public FilteredLogFileReader(string logFileName, string entlibLogConfigFile, ITimeStampParser theTimeStampParser)
			: this(logFileName, new FileConfigurationSource(entlibLogConfigFile), theTimeStampParser)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FilteredLogFileReader"/> class.
		/// </summary>
		/// <param name="logFileName">Name of the log file.</param>
		/// <param name="entLibLogConfig">The ent lib log config.</param>
		public FilteredLogFileReader(string logFileName, IConfigurationSource entLibLogConfig)
			: this(logFileName, entLibLogConfig, null)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FilteredLogFileReader"/> class.
		/// </summary>
		/// <param name="logFileName">Name of the log file.</param>
		/// <param name="entLibLogConfig">The ent lib log config.</param>
		/// <param name="theTimeStampParser">The time stamp parser to use</param>
		public FilteredLogFileReader(string logFileName, IConfigurationSource entLibLogConfig, ITimeStampParser theTimeStampParser)
		{
			if (String.IsNullOrEmpty(logFileName))
				throw new ArgumentException("file argument is null or empty");

			if (entLibLogConfig == null)
				throw new ArgumentNullException("entLibLogConfig");

			myFileName = logFileName;

			RegularExpressionBuilder builder = new RegularExpressionBuilder(entLibLogConfig);
			if (theTimeStampParser != null)
				myTokenizer = new Tokenizer(builder, theTimeStampParser);
			else
				myTokenizer = new Tokenizer(builder);
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Parses the log file.
		/// </summary>
		/// <param name="filter">The filter.</param>
		/// <returns></returns>
		public IEnumerable<LogEntry> ParseLogFile(Filter filter)
		{
			string logFile = FileIO.ReadAllText(myFileName);

			foreach (LogEntry ent in myTokenizer.GetDeserializedLogEntries(logFile, myFileName))
			{
				if (filter.Match(ent))
					yield return ent;
			}
		}
		#endregion

		#region IEnumerable<LogEntry> Members

		/// <summary>
		/// Gets the enumerator.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
		/// </returns>
		public IEnumerator<LogEntry> GetEnumerator()
		{
			string logFile = FileIO.ReadAllText(myFileName);

			foreach (LogEntry ent in myTokenizer.GetDeserializedLogEntries(logFile, myFileName))
			{
				yield return ent;
			}
		}

		#endregion

		#region IEnumerable Members

		/// <summary>
		/// Gets the enumerator.
		/// </summary>
		/// <returns>
		/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
		/// </returns>
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		#endregion
	}
}
